<?php

declare(strict_types=1);

namespace App\Controller\Admin;

use App\Model\Device;
use App\Model\Distributors;
use App\Model\Order;
use App\Model\OrderDetail;
use App\Model\Station;
use App\Model\User;
use Hyperf\Redis\Redis;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Contract\RequestInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Trait\ResponseMsg;
use App\Model\Normal;
use Hyperf\Di\Annotation\Inject;
use App\Controller\AbstractController;
use App\Model\Admin\Admin;


class StaticsController extends AbstractController
{
    use ResponseMsg;

    protected Redis $redis;
    protected Normal $normal;

    #[Inject]
    protected Device $device;

    #[Inject]
    protected Admin $admin;


    public function __construct()
    {
        $this->redis = container()->get(Redis::class);
        $this->normal = container()->get(Normal::class);
    }

    /**获取后台背景图
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getBackImage(): ResponseInterface
    {
        $data['url'] = $this->redis->get('back_admin_img');
        return $this->success($data);
    }

    /**卡片统计
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function scrollNum(RequestInterface $request): ResponseInterface
    {
        $data = $request->inputs(['distributor_id', 'stations', 'start', 'end']);
        $info = $this->admin->getInfo($request);

// 处理分销商ID逻辑保持不变
        if (!isset($data['distributor_id']) || !$data['distributor_id']) {
            if (isset($info['distributor_id'])) {
                $data['distributor_id'] = $info['distributor_id'];
            }
        }

// 添加时间范围筛选条件函数
        $addTimeRange = function ($query) use ($data) {
            if (isset($data['start']) && $data['start'] && isset($data['end']) && $data['end']) {
                $query->whereBetween('stop_at', [$data['start'], $data['end']]);
            }
            return $query;
        };

        if ($data['distributor_id']) {
            $distributor = Distributors::find($data['distributor_id']);
            if (!$distributor->parent_id) {
                $distributors = Distributors::where('parent_id', $distributor->id)->pluck('id')->toArray();
                array_push($distributors, $distributor->id);

                // 设备统计（保持不变）
                $data['off'] = Device::whereIn('distributor_id', $distributors)
                    ->where('inline', 0)->count();
                $data['inline'] = Device::whereIn('distributor_id', $distributors)
                    ->where('inline', 1)->count();

                // 订单统计（添加时间范围筛选）
                $data['orders'] = $addTimeRange(Order::whereIn('distributor_id', $distributors)
                    ->where('status', Order::STATUS_END))
                    ->count();

                $data['using'] = Order::whereIn('distributor_id', $distributors)
                    ->where('status', Order::STATUS_USING)
                    ->count();

                $data['income'] = $addTimeRange(Order::whereIn('distributor_id', $distributors)
                    ->where('status', Order::STATUS_END))
                    ->sum('fee');

                $data['return_fee'] = $addTimeRange(Order::whereIn('distributor_id', $distributors)
                    ->where('status', Order::STATUS_END))
                    ->sum('return_fee');

                $data['elec'] = $addTimeRange(Order::whereIn('distributor_id', $distributors)
                    ->where('status', Order::STATUS_END))
                    ->whereHas('detail')
                    ->with('detail')
                    ->get()
                    ->sum(function ($order) {
                        return $order->detail ? $order->detail->elec : 0;
                    });
            } else {
                // 设备统计（保持不变）
                $data['off'] = Device::where('distributor_id', $data['distributor_id'])
                    ->where('inline', 0)->count();
                $data['online'] = Device::where('distributor_id', $data['distributor_id'])
                    ->where('inline', 1)->count();

                // 订单统计（添加时间范围筛选）
                $data['orders'] = $addTimeRange(Order::where('distributor_id', $data['distributor_id'])
                    ->where('status', Order::STATUS_END))
                    ->count();

                $data['using'] = Order::where('distributor_id', $data['distributor_id'])
                    ->where('status', Order::STATUS_USING)
                    ->count();

                $data['income'] = $addTimeRange(Order::where('distributor_id', $data['distributor_id'])
                    ->where('status', Order::STATUS_END))
                    ->sum('fee');

                $data['return_fee'] = $addTimeRange(Order::where('distributor_id', $data['distributor_id'])
                    ->where('status', Order::STATUS_END))
                    ->sum('return_fee');

                $data['elec'] = $addTimeRange(Order::where('distributor_id', $data['distributor_id'])
                    ->where('status', Order::STATUS_END))
                    ->whereHas('detail')
                    ->with('detail')
                    ->get()
                    ->sum(function ($order) {
                        return $order->detail ? $order->detail->elec : 0;
                    });
            }
        } else {
            // 设备统计（保持不变）
            $data['off'] = Device::where('inline', 0)->count();
            $data['online'] = Device::where('inline', 1)->count();

            // 订单统计（添加时间范围筛选）
            $data['orders'] = $addTimeRange(Order::where('status', Order::STATUS_END))
                ->count();

            $data['using'] = Order::where('status', Order::STATUS_USING)
                ->count();

            $data['income'] = $addTimeRange(Order::where('status', Order::STATUS_END))
                ->sum('fee');

            $data['return_fee'] = $addTimeRange(Order::where('status', Order::STATUS_END))
                ->sum('return_fee');

            $data['elec'] = $addTimeRange(Order::where('status', Order::STATUS_END))
                ->whereHas('detail')
                ->with('detail')
                ->get()
                ->sum(function ($order) {
                    return $order->detail ? $order->detail->elec : 0;
                });

        }

        return $this->success($data);
    }

    /**获取chartData
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function chartData(): ResponseInterface
    {
        $now = new \DateTime();
        $startOfDay = clone $now;
        $startOfDay->setTime(0, 0, 0);
        $now->setTime(23, 59, 59);
        $i = 0;
        $data['expectedData'] = [];
        while ($startOfDay <= $now) {
            if ($i > 24) {
                break;
            }
            $start = $startOfDay->format('Y-m-d H:i:s');
            // 移动到下一个小时
            $end = $startOfDay->modify('+1 hour')->format('Y-m-d H:i:s');
            $powerfee = Order::where('stop_at', '>=', $start)
                ->where('stop_at', '<=', $end)
                ->sum('fee');
            $returnfee = Order::where('stop_at', '>=', $start)
                ->where('stop_at', '<=', $end)
                ->sum('return_fee');
            $insideFee = number_format($powerfee - $returnfee, 2);
            $data['expectedData'][] = $insideFee;
//            $data['now_total'] += $tempArr['power'];
            $i++;
        }
        return $this->success($data);
    }

    /**获取pieChart
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function pieData(): ResponseInterface
    {
        $data['pieChartData'] = [];
        $array = [1, 2];
        foreach ($array as $k => $v) {
            if ($v == 1) {
                $data['pieChart'][] = '微信用户';
                $data['pieChartData'][$k]['name'] = '微信用户';
            } else {
                $data['pieChart'][] = '支付宝用户';
                $data['pieChartData'][$k]['name'] = '支付宝用户';
            }
            $data['pieChartData'][$k]['value'] = User::where('login_type', $v)
                ->count();
        }
        return $this->success($data);
    }

    /**获取lineChart
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getMonth(RequestInterface $request): ResponseInterface
    {
        $data['line'] = [];
        $data['count'] = [];
        $data = $request->inputs(['distributor_id', 'stations'] );
        $info = $this->admin->getInfo($request);
// 处理分销商ID逻辑保持不变
        if (!isset($data['distributor_id']) || !$data['distributor_id']) {
            if (isset($info['distributor_id'])) {
                $data['distributor_id'] = $info['distributor_id'];
            }
        }
        if($data['stations']){
            if(!is_array($data['stations'])){
                $data['stations'] = json_decode($data['stations']);
            }
        }
        for ($i = 1; $i <= 12; $i++) {
            if ($i < 10) {
                $start = date("Y-0{$i}-01 00:00:00");
                $end = date("Y-0" . ($i + 1) . "-01 00:00:00");
            } else {
                $start = date("Y-{$i}-01 00:00:00");
                if ($i == 12) {
                    $end = date("Y-" . ($i) . "-31 23:59:59");
                } else {
                    $end = date("Y-" . ($i + 1) . "-01 00:00:00");
                }
            }
            array_push($data['line'], "{$i}月");
            if($data['stations']){
                $data['data'][] = Order::where('stop_at', '>=', $start)
                    ->where('stop_at', '<=', $end)
                    ->whereIn('station_id',$data['stations'])
                    ->count();
            }else{
                if($data['distributor_id']){
                    $data['data'][] = Order::where('stop_at', '>=', $start)
                        ->where('stop_at', '<=', $end)
                        ->where('distributor_id',$data['distributor_id'])
                        ->count();
                }else{
                    $data['data'][] = Order::where('stop_at', '>=', $start)
                        ->where('stop_at', '<=', $end)
                        ->count();
                }
            }
//                 $fee= Order::where('stop_at','>=',$start)
//                    ->where('stop_at','<=',$end)
//                    ->sum('fee');
//                 $refund = Order::where('stop_at','>=',$start)
//                     ->where('stop_at','<=',$end)
//                     ->sum('return_fee');
//                $data['data'][]  = number_format($fee-$refund,2);
        }
        return $this->success($data);
    }


    /**获取附近电站
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getNearDevice(RequestInterface $request)
    {
        try {
            $lat = $request->input('lat');
            $lng = $request->input('lng');
            $token = $request->header('Token');
            if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
                return $this->error(1001, 'token无效');
            }
            $distance = $request->input('distance', 2); // 默认距离为1000米
            $list = Device::queryNearbyStations((float)$lng, (float)$lat, (float)$distance);
            $data = [];
            foreach ($list as $k => &$v) {
                $v['station'] = Station::where('id', $v[0])->where('is_active', 1)
//                    ->whereNotNull('cameraCode')
//                    ->whereNotNull('mainDeviceCode')
                    ->withCount('device')
                    ->first(['id', 'name', 'address', 'lat', 'lng', 'province', 'city', 'area', 'street', 'created_at', 'cameraCode', 'mainDeviceCode']);
                if (!$v['station']) {
                    unset($list[$k]);
                } else {
                    if ($v['station']->device_count <= 0) {
                        unset($list[$k]);
                    } else {
                        $data[] = $v;
                    }
                }
            }
            usort($data, function ($a, $b) {
                return $a[1] <=> $b[1];
            });

            return $this->success($data);
        } catch (\Exception $e) {
            Normal::logger($e->getMessage() . $e->getTraceAsString(), 'home');
            return $this->error(500, $e->getMessage());
        }
    }

    public function getStationDetail(RequestInterface $request)
    {
        $id = $request->input('station_id');
        $start = $request->input('start');
        $end = $request->input('end');
        $token = $request->header('Token');
        if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
            return $this->error(1001, 'token无效');
        }
        if (!$start || !$end) {
            return $this->error(1001, '起止时间为必选项');
        }
        $start1 = new \DateTime($start);
        $end1 = new \DateTime($end);

// 计算差值
        $interval = $start1->diff($end1);
        $days = $interval->days;
        $days += 1;
        $station = Station::where('id', $id)
            ->with(['device' => function ($query) {
                $query->select('id', 'inline', 'channel', 'station_id'); // 只获取 id 字段
            }])
            ->withCount('device')
            ->first();
        $station->port_count = $station->device->sum('channel');

        try {
            $station->offCount = 0;
            foreach ($station->device as $v) {
                if ($v->inline != 1) {
                    $station->offCount++;
                }
            }
            $result = Order::where('station_id', $id)
                ->where('status', Order::STATUS_END)
                ->whereBetween('created_at', [$start . ' 00:00:00', $end . ' 23:59:59'])
                ->selectRaw('AVG(fee - return_fee) as avg_use_fee, COUNT(*) as total_count')
                ->first();
            $station->avg_fee_diff = $result->avg_fee_diff ?? 0;  // 若没有数据，默认为 0
            $station->order_count = $orderCount = $result->total_count;
            if ($orderCount > 0 && $station->port_count) {
                $station->day_use_rate = round($orderCount / ($station->port_count * $days), 4) * 100;
            } else {
                $station->day_use_rate = 0;
            }

            $today = date('Y-m-d', time());
            $start_today = $today . ' 00:00:00';
            $end_today = $today . ' 23:59:59';

            $station->using_order_today = Order::where('station_id', $id)
                ->where('status', Order::STATUS_USING)->count();
            $station->end_count_today = Order::where('station_id', $id)
                ->where('status', Order::STATUS_END)
                ->where('created_at', '>=', $start_today)
                ->where('created_at', '<=', $end_today)->count();
            $station->free_device_port = $station->port_count - $station->using_order_count;
            $station->charge = Device::getCharge($station->charge_id);
            return $this->success($station);
        } catch (\Exception $e) {
            Normal::logger($e->getMessage() . $e->getTraceAsString(), 'home');
            return $this->error(500, '操作繁忙');
        }
    }

    public function getTodayAreaData(RequestInterface $request)
    {
        $token = $request->header('Token');
        if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
            return $this->error(1001, 'token无效');
        }
        $districts = $request->input('districts');
        if (!$districts) {
            return $this->error(1001, '请传入区/县城code');
        }
        if (!is_array($districts)) {
            $districts = json_decode($districts, true);
        }
        $data['pieChartData'] = [];
        foreach ($districts as $k => $v) {
            $data['pieChart'][] = $v['area'];
            $data['pieChartData'][$k]['area'] = $v['area'];
            $data['pieChartData'][$k]['area_code'] = $v['area_code'];
            $stations = Station::where('area_code', $v['area_code'])->pluck('id')->toArray();
            $result = Order::whereIn('station_id', $stations)
                ->where('status', Order::STATUS_END)
                ->whereBetween('created_at', [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')])
                ->select([
                    DB::raw('COUNT(*) as order_count'),
                    DB::raw('SUM(fee) as total_fee'),
                    DB::raw('SUM(return_fee) as total_return_fee')
                ])
                ->first();
            $data['pieChartData'][$k]['count'] = $result->order_count ?? 0;
            $data['pieChartData'][$k]['income_fee'] = $result->total_fee ?? 0;
            $data['pieChartData'][$k]['return_fee'] = $result->total_return_fee ?? 0;
            $data['pieChartData'][$k]['use_fee'] = round($data['pieChartData'][$k]['income_fee'] - $data['pieChartData'][$k]['return_fee'], 2);
        }
        return $this->success($data);
    }


    /**获取lineChart
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function userChart(RequestInterface $request): ResponseInterface
    {

        $token = $request->header('Token');
        if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
            return $this->error(1001, 'token无效');
        }
        $start = $request->input('start');
        $end = $request->input('end');
        // 定义起始日期和结束日期
        $startDate = new \DateTime($start);
        $endDate = new \DateTime($end);
        $interval = $startDate->diff($endDate);

// 计算绝对天数差（无论日期顺序）
//        if ($interval->days > 31) {
//            return $this->error(1001,'因数据量较大，大范围搜索较为占用资源，统计表格数据时起止日期不可超过1个月');
//        }
// 初始化存储日期的数组
        $data['line'] = [];
        $data['data'] = [];
// 循环生成每一天
        while ($startDate <= $endDate) {
            $data['line'][] = $tempDate = $startDate->format('Y-m-d'); // 格式化为字符串
            $startDate->modify('+1 day'); // 增加一天

            $data['data'][] = User::whereBetween('last_login', [$tempDate . ' 00:00:00', $tempDate . ' 23:59:59'])->count();
        }

        return $this->success($data);
    }

    public function allStatstics(RequestInterface $request)
    {
        $token = $request->header('Token');
        if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
            return $this->error(1001, 'token无效');
        }
        $data['stations'] = Station::count();
        $data['users'] = User::count();
        $data['orders'] = Order::whereIn('status', [Order::STATUS_REFUNDED, Order::STATUS_END])
            ->count();
        $allKey = 'ALL_ORDER_PROFIT';
        if ($this->redis->exists($allKey)) {
            $data['profit'] = $this->redis->get($allKey);
            $data['profit'] = number_format((float)$data['profit'], 2, '.', '');
        } else {
            $this->redis->set($allKey, '0.15');
        }
        return $this->success($data);
    }


    public function allDevice(RequestInterface $request)
    {
        $token = $request->header('Token');
        if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
            return $this->error(1001, 'token无效');
        }
//        $areaCode = $request->input('area_code');
        $deviceQuery = Device::query();
        $orderQuery = Order::query();
//        if($areaCode){
//            $stations = Station::where('area_code',$areaCode)->pluck('id')->toArray();
//            $deviceQuery->whereIn('station_id',$stations);
//            $orderQuery->whereIn('station_id',$stations);
//        }
        $data['all'] = $deviceQuery->count();
        $data['online'] = $deviceQuery->where('inline', 1)->count();
        $data['offline'] = $data['all'] - $data['online'];
        $data['using'] = $orderQuery->where('status', Order::STATUS_USING)
            ->distinct('device_id')
            ->count('device_id');
        return $this->success($data);

    }


    /**
     * 标准化区域名称（合并类似"金东"和"金东区"）
     */
    private function normalizeAreaName(array $areas): string
    {
        if (count($areas) === 1) {
            return $areas[0];
        }

        // 优先级：区 > 县 > 市 > 其他
        $prioritySuffixes = ['区', '县', '市'];

        foreach ($prioritySuffixes as $suffix) {
            foreach ($areas as $name) {
                if (mb_substr($name, -1) === $suffix) {
                    return $name;
                }
            }
        }

        // 返回最长或最短的名称（可根据业务需求调整）
        return $this->getMostReasonableName($areas);
    }

    private function getMostReasonableName(array $names): string
    {
        // 方案1：返回最短的名称（通常是无后缀的）
        usort($names, function ($a, $b) {
            return mb_strlen($a) <=> mb_strlen($b);
        });
        return $names[0];

        // 或方案2：返回最长的名称（通常是带后缀的）
        // usort($names, function($a, $b) {
        //     return mb_strlen($b) <=> mb_strlen($a);
        // });
        // return $names[0];
    }

    public function stationGroup(RequestInterface $request)
    {
        $token = $request->header('Token');
        if ($token != 'd7e62e6a55120894c5b8144ac6614a8c') {
            return $this->error(1001, 'token无效');
        }
        $result = Station::select([
            'area_code',
            DB::raw('COUNT(*) as total_count'),
            DB::raw('GROUP_CONCAT(DISTINCT area SEPARATOR "|") as area_names')
        ])
            ->groupBy('area_code')
            ->get()
            ->map(function ($item) {
                // 处理区域名称合并逻辑
                $areas = array_unique(explode('|', $item->area_names));
                $item->area = $this->normalizeAreaName($areas);
                unset($item->area_names);
                return $item;
            });
        foreach ($result as &$item) {
            $stations = Station::where('area_code', $item->area_code)->pluck('id')->toArray();
            $item->device_count = Device::whereIn('station_id', $stations)->count();
        }
        return $this->success($result);
    }


}
